package com.amtf.datafile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.jdom.JDOMException;

import com.amtf.fio.MyFileAccessor;

// version 2.0
public class DataFile extends File {
	private static final long serialVersionUID = -4322774245588565517L;

	private DataRecordDefinition _definition = null;
	private MyFileAccessor _accessor = null;
	private boolean _firstRowTitle = false;

	// public DataFile(File file) {
	// super(file);
	// this._definition = new DataRecordDefinition();
	// }

	public DataFile(DataRecordDefinition definition, InputStream customeInStream) {
		super("");
		_accessor = new MyFileAccessor(customeInStream, definition.getEncoding());
		this._definition = definition;
		this._firstRowTitle = definition.isFirstRowTitle();

	}

	public DataFile(DataRecordDefinition definition, File file) {
		this(definition, file.getAbsolutePath());
	}

	public DataFile(DataRecordDefinition definition, String file) {
		super(file);
		_accessor = new MyFileAccessor(this, definition.getEncoding());
		this._definition = definition;
		this._firstRowTitle = definition.isFirstRowTitle();
	}

	/**
	 * Convert content to DataRecord
	 * 
	 * @param content
	 * @return
	 * @throws IOException
	 * @throws FormatNotMatchException
	 */
	private List<DataRecord> toDataRecordList(List<String> content) throws FormatNotMatchException {
		if (content != null && content.size() != 0) {
			ArrayList<DataRecord> records = new ArrayList<DataRecord>();

			int totalSize = content.size();
			int index = totalSize;

			// If format is correct
			for (int i = 0; i < totalSize; i++) {
				index--;

				String row = content.get(i);// .replace("\n", "").replaceAll("\r", "");
				if (row.length() != 0) {
					DataRecord record = null;
					try {
						record = DataRecord.parseRecord(_definition, row);
					} catch (Throwable e) {
						String msg = e.getMessage();
						// throw new FormatNotMatchException("Could not parse record at row (" + (_reader.getCurrentLineNumber() - index) +
						// "), " + msg);
						throw new FormatNotMatchException("このレコードを解析できません。行(" + (_accessor.getCurrentLineNumber() - index) + "), " + msg);
					}
					records.add(record);
				}
			}

			return records;
		}

		return null;
	}

	public List<DataRecord> readAllDataRecords() throws IOException, FormatNotMatchException {
		DataRecord record = this.readFirstDataRecord();
		if (record == null) {
			return null;
		} else {
			ArrayList<DataRecord> records = new ArrayList<DataRecord>();

			do {
				records.add(record);
				record = this.readFirstDataRecord();
			} while (record != null);

			return records;
		}
	}

	public long getRecordCount() throws IOException, FormatNotMatchException {
		return _accessor.getTotalLines();
	}

	public List<DataRecord> readFirstDataRecords(int readRowCount) throws IOException, FormatNotMatchException {
		// Get the content of this file
		List<String> content = _accessor.readFirstLines(readRowCount);

		if (_firstRowTitle && content.size() > 0) {
			content.remove(0);
		}

		return toDataRecordList(content);
	}

	public List<DataRecord> readNextDataRecords(int readRowCount) throws IOException, FormatNotMatchException {
		// Get the content of this file
		List<String> content = _accessor.readNextLines(readRowCount);

		return toDataRecordList(content);
	}

	private DataRecord toDataRecord(String content) throws FormatNotMatchException {
		if (content != null && content.length() != 0) {
			DataRecord record = null;
			try {
				record = DataRecord.parseRecord(_definition, content);
			} catch (Throwable e) {
				String msg = e.getMessage();
				// throw new FormatNotMatchException("Could not parse record at row (" + _reader.getCurrentLineNumber() + "), " + msg);
				throw new FormatNotMatchException("このレコードを解析できません。行(" + _accessor.getCurrentLineNumber() + "), " + msg);
			}

			return record;
		}

		return null;
	}

	// public String readFirstString() throws IOException, FormatNotMatchException {
	// String content = null;
	// if (_firstRowTitle) {
	// _accessor.readFirstLine();
	// content = _accessor.readNextLine();
	// } else {
	// // Get the content of this file
	// content = _accessor.readFirstLine();
	// }
	//
	// return content;
	// }
	//
	// public String readNextString() throws IOException, FormatNotMatchException {
	// return _accessor.readNextLine();
	// }

	public DataRecord readFirstDataRecord() throws IOException, FormatNotMatchException {
		String content = null;
		if (_firstRowTitle) {
			_accessor.readFirstLine();
			content = _accessor.readNextLine();
		} else {
			// Get the content of this file
			content = _accessor.readFirstLine();
		}

		return toDataRecord(content);
	}

	public DataRecord readNextDataRecord() throws IOException, FormatNotMatchException {
		// Get the content of this file
		String content = _accessor.readNextLine();

		return toDataRecord(content);
	}

	public boolean createWriter() throws IOException {
		return _accessor.createWriter();
	}

	public boolean createWriter(boolean append) throws IOException {
		return _accessor.createWriter(append);
	}

	public boolean createWriter(OutputStream outStream) throws IOException {
		return _accessor.createWriter(outStream);
	}

	public void write(List<DataRecord> records) throws IOException {
		StringBuffer content = new StringBuffer();

		if (records != null) {
			for (DataRecord record : records) {
				content.append(DataRecord.toString(record.getFields(), this._definition));
				content.append(this._definition.getRowTerminator());
			}
		}

		_accessor.write(content.toString());
	}

	public void writeTitle() throws IOException {
		DataRecord titlerec = this._definition.newDataRecordInstance();
		for (DataField fd : titlerec.getFields()) {
			fd.setValue(fd.getName());
		}
		_accessor.write(DataRecord.toString(titlerec.getFields(), this._definition) + this._definition.getRowTerminator());
	}

	public DataRecord getTitle() {
		DataRecord titlerec = this._definition.newDataRecordInstance();
		for (DataField fd : titlerec.getFields()) {
			fd.setValue(fd.getName());
		}

		return titlerec;
	}

	// public void write(File toFile) throws IOException {
	// DataFile toDF = new DataFile(this._definition, toFile);
	// toDF.createWriter();
	// }

	public void write(DataRecord record) throws IOException {
		_accessor.write(DataRecord.toString(record.getFields(), this._definition) + this._definition.getRowTerminator());
	}

	public void writeValue(List<DataRecord> records) throws IOException {
		StringBuffer content = new StringBuffer();

		if (records != null) {
			for (DataRecord record : records) {
				content.append(DataRecord.toValue(record.getFields(), this._definition));
				content.append(this._definition.getRowTerminator());
			}
		}

		_accessor.write(content.toString());
	}

	public void writeValue(DataRecord record) throws IOException {
		_accessor.write(DataRecord.toValue(record.getFields(), this._definition) + this._definition.getRowTerminator());
	}

	public void closeWriter() {
		_accessor.closeWriter();
	}

	public boolean isReadTitle() {
		return _firstRowTitle;
	}

	public void setReadTitle(boolean readTitle) {
		this._firstRowTitle = readTitle;
	}

	public boolean isRowMatch(int rowNumber) {
		if (rowNumber <= 0) {
			return false;
		}

		String content = null;
		try {
			// Get the content of this file
			content = _accessor.readFirstLine();
			while (_accessor.getCurrentLineNumber() != rowNumber) {
				content = _accessor.readNextLine();
			}
		} catch (Throwable e) {
			return false;
		} finally {
			_accessor.closeReader();
		}

		if (content == null) {
			return false;
		}

		return DataRecord.isRecordMatch(_definition, content);
	}

	public DataRecordDefinition getDefinition() {
		return _definition;
	}

	public MyFileAccessor getFileReader() {
		return _accessor;
	}

	public void closeReader() {
		_accessor.closeReader();
	}

	public static void main(String[] s) throws ClassNotFoundException, JDOMException, IOException, FormatNotMatchException {
		// String row = "";
		int i = 0;
		File cvs = new File("C:\\Documents and Settings\\HANSONG.MCDOMAIN\\Desktop\\TEMP\\※JOCMMS_Test_Data\\Global_Customer_Master_50W.csv");
		// File cvs = new File("C:\\temp\\Global_Customer_Master.csv");
		// File def = new File("C:\\temp\\DataFileDef_([GLOBAL].[Global_Customer_Master]).xml");
		DataFile df = new DataFile(DataRecordDefinition.DEFAULT_CSV_DEFINITION, cvs);

		long t1 = System.currentTimeMillis();

		DataRecord record = df.readFirstDataRecord();
		while (record != null) {
			// System.out.println(record);
			i++;
			record = df.readNextDataRecord();
		}

		long t2 = System.currentTimeMillis();
		System.out.println(t2 - t1);

		main(null);

	}
}
